/**
 * 该插件可根据菜单配置自动生成 ANTD menu组件
 * menuOptions示例：
 * [
 *  {
 *    name: '菜单名称',
 *    path: '菜单路由',
 *    hidden:'boolean, 是否不可见, 默认 false',
 *    meta: {
 *      icon: '菜单图标',
 *      title: '菜单标题',
 *    },
 *    children: [子菜单配置]
 *  },
 *  {
 *    name: '菜单名称',
 *    path: '菜单路由',
 *    hidden:'boolean, 是否不可见, 默认 false',
 *    meta: {
 *      icon: '菜单图标',
 *      title: '菜单标题',
 *    },
 *    children: [子菜单配置]
 *  }
 * ]
 *
 * i18n: 国际化配置。系统默认会根据 options route配置的 path 和 name 生成英文以及中文的国际化配置，如需自定义或增加其他语言，配置
 * 此项即可。如：
 * i18n: {
 *   messages: {
 *     CN: {dashboard: {name: '监控中心'}}
 *     HK: {dashboard: {name: '監控中心'}}
 *   }
 * }
 **/
import Menu from 'ant-design-vue/es/menu'
import Icon from 'ant-design-vue/es/icon/'
import fastEqual from 'fast-deep-equal'
// import Link from './Link'

const { Item, SubMenu } = Menu

// 默认菜单图标数组，如果菜单没配置图标，则会设置从该数组随机取一个图标配置
const iconArr = ['dashboard', 'user', 'form', 'setting', 'message', 'safety', 'bell', 'delete', 'code-o', 'poweroff', 'eye-o', 'hourglass']

export default {
  name: 'IMenu',
  props: {
    menuData: {
      type: Array,
      required: true
    },
    theme: {
      type: String,
      required: false,
      default: 'dark'
    },
    mode: {
      type: String,
      required: false,
      default: 'inline'
    },
    collapsed: {
      type: Boolean,
      required: false,
      default: false
    }
  },
  data() {
    return {
      selectedKeys: [],
      sOpenKeys: [],
      cachedOpenKeys: []
    }
  },
  computed: {},
  created() {
    this.updateMenu()
  },
  watch: {
    collapsed(val) {
      if (val) {
        this.cachedOpenKeys = this.sOpenKeys
        this.sOpenKeys = []
      } else {
        this.sOpenKeys = this.cachedOpenKeys
      }
    },
    $route: function() {
      this.updateMenu()
    },
    sOpenKeys(val) {
      this.$emit('openChange', val)
      this.$emit('update:openKeys', val)
    }
  },
  methods: {
    renderIcon: function(h, icon) {
      return icon === 'none'
        ? null
        : h(Icon, {
            props: { type: !!icon ? icon : iconArr[Math.floor(Math.random() * iconArr.length)] }
          })
    },
    renderMenuItem: function(h, menu) {
      return h(Item, { key: menu.path }, [
        h('router-link', { props: { to: menu.path }, attrs: { style: 'overflow:hidden;white-space:normal;text-overflow:clip;' } }, [
          this.renderIcon(h, menu.meta ? menu.meta.icon : 'none', menu.path),
          menu.name /* this.$t(menu.name) */
        ])
      ])
    },
    renderSubMenu: function(h, menu, pIndex, index) {
      var this2_ = this

      var subItem = [h('span', { slot: 'title' }, [this.renderIcon(h, menu.meta.icon), h('span', [menu.name])])]
      var itemArr = []
      var pIndex_ = pIndex + '_' + index
      menu.children.forEach(function(item, i) {
        itemArr.push(this2_.renderItem(h, item, pIndex_, i))
      })
      return h(SubMenu, { key: menu.path ? menu.path : 'submenu_' + pIndex + '_' + index }, subItem.concat(itemArr))
    },
    renderItem: function(h, menu, pIndex, index) {
      if (!menu.hidden) {
        return menu.children && menu.children.length > 0 ? this.renderSubMenu(h, menu, pIndex, index) : this.renderMenuItem(h, menu, pIndex, index)
      }
    },
    renderMenu: function(h, menuTree) {
      var this2_ = this
      var menuArr = []
      menuTree.forEach(function(menu, i) {
        menuArr.push(this2_.renderItem(h, menu, '0', i))
      })
      return menuArr
    },
    updateMenu() {
      const menuRoutes = this.$route.matched.filter((item) => item.path !== '')
      this.selectedKeys = this.getSelectedKey(this.$route)
      let openKeys = menuRoutes.map((item) => item.path)
      if (!fastEqual(openKeys, this.sOpenKeys)) {
        this.collapsed || this.mode === 'horizontal' ? (this.cachedOpenKeys = openKeys) : (this.sOpenKeys = openKeys)
      }
    },
    getSelectedKey(route) {
      return route.matched.map((item) => item.path)
    }
  },
  render(h) {
    return h(
      Menu,
      {
        props: {
          theme: this.$props.theme,
          mode: this.$props.mode,
          selectedKeys: this.selectedKeys,
          openKeys: this.openKeys ? this.openKeys : this.sOpenKeys
        },
        on: {
          'update:openKeys': (val) => {
            this.sOpenKeys = val
          },
          select: (obj) => {
            this.selectedKeys = obj.selectedKeys
            this.$emit('select', obj)
          }
        }
      },
      this.renderMenu(h, this.menuData)
    )
  }
}
